/**
 * @file bitLogic.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2025-04-29
 *
 * @copyright Copyright (c) 2025
 *
 */

#include "bitLogic.h"
#include "delay.h"


/// @brief 线圈逻辑：根据使能输入对布尔变量进行赋值（或赋值取反）
/// @param in 使能输入（通常是前面逻辑计算结果）
/// @param operand 要赋值的布尔变量（通过指针）
/// @param Negated 是否取反赋值
/// @return 返回 true（或按需返回 in）
Bool Coil(Bool in, Bool* operand, Bool Negated) {
    if (operand == NULL) return false; // 防止空指针
	  if(Negated){
		  *operand = in?0:1;
	  }else{
			*operand = in?1:0;
		}
    return in; // 或者 return in; 取决于你的 ENO（输出使能）设计
}


/// @brief 触点 （常开、常闭）
/// @param in 使能
/// @param operand 操作数
/// @param Negated =true 常闭触点，=false常开触点
/// @return 
Bool Contact(Bool in, Bool operand , Bool Negated) {
  if(!in) {
    return false;
  }
  if(Negated){
    return !operand;
  }else{
    return operand;
  }
}

/// @brief RCoil：复位线圈（输入为 true 时，将输出变量复位为 false）
/// @param in 输入信号（使能复位）
/// @param operand 指向目标变量的指针
/// @return 返回 true，表示已执行
Bool RCoil(Bool in, Bool* operand) {
    if (operand == NULL) return false; // 防止空指针

    if (in) {
        *operand = false; // 复位操作
    }
    return in;
}


/**
 * @brief 置位输出
 *
 * @param in 能流输入（true 表示 RLO = “1”，false 表示 RLO = “0”）
 * @param operand 指向操作数的指针，表示要置位的信号状态
 * @return Bool
 */
/**
 * @brief Sets a boolean value based on input condition.
 * @param in Input condition to evaluate.
 * @param operand Pointer to the boolean value to set.
 * @return true if operation succeeded, false if input condition is false.
 */
Bool SCoil(Bool in, Bool* operand) {
     if (operand == NULL) return false; // 防止空指针
  if(in) {
    *operand = true;
  }
  return in;
}



/**
 * @brief 扫描操作数的信号上升沿
 * @note 可以确定所指定操作数（operand）的信号状态是否从“0”变为“1”。该指令将比较
 * <operand>
 * 的当前信号状态与上一次扫描的信号状态，上一次扫描的信号状态保存在边沿存储位（bit）中。如果该指令检测到逻辑运算结果
 * (RLO)
 * 从“0”变为“1”，则说明出现了一个上升沿。每次执行指令时，都会查询信号上升沿。检测到信号上升沿时，<operand>
 * 的信号状态将在一个程序周期内保持置位为“1”。在其它任何情况下，操作数的信号状态均为“0”。在该指令上方的操作数占位符中，指定要查询的操作数（operand）。在该指令下方的操作数占位符中，指定边沿存储位（bit）。
 *
 * @param pre 能流
 * @param bit 边沿存储位，保存上一次的信号状态 (通过指针更新)
 * @param operand 当前操作数的信号状态 (0 或 1)
 * @return Bool
 */
Bool PContact(Bool pre, Bool operand, Bool* bit) {
     if (bit == NULL) return false;
  /* 如果没有能流，直接返回 false*/
  if(!pre) {
		*bit = operand;
    return false;
  }
  Bool res = false;
  /*检查上升沿：上一次状态为 0，当前状态为 1*/
  if(!(*bit) && operand) {
    res = true; /*检测到上升沿，置位为 1*/
  }

  *bit = operand; /*更新边沿存储位为当前状态*/
  return res;
}

/**
 * @brief 扫描操作数的信号下降沿
 * 该函数检查当能流有效时，操作数的信号状态是否从“1”变为“0”（下降沿）。
 * 它将当前操作数状态与存储在边沿存储位中的上一次状态进行比较。
 * 如果检测到下降沿，结果在一个程序周期内置位为“1”。
 * 仅当能流有效时，才更新边沿存储位。
 *
 * @param pre 能流输入（true 表示启用检测，false 表示禁用）
 * @param bit 指向边沿存储位的指针，保存上一次信号状态
 * @param operand 当前操作数的信号状态（0 或 1）
 * @return Bool 如果检测到下降沿且能流有效，返回 true（1）；否则返回 false（0）
 */
Bool NContact(Bool pre, Bool operand, Bool* bit) {
   if (bit == NULL) return false;
  // 如果没有能流，直接返回 false，不更新边沿存储位
  if(!pre) {
		*bit = operand;
    return false;
  }
  Bool res = false;

  // 检查下降沿：上一次状态为 1，当前状态为 0
  if(*bit && !operand) {
    res = true; // 检测到下降沿，置位为 1
  }
  // 更新边沿存储位为当前操作数状态
  *bit = operand;
  return res;
}


/**
 * @brief 在信号上升沿置位操作数
 *
 * 该函数检测逻辑运算结果（RLO）的上升沿（从“0”变为“1”），并在检测到上升沿时将指定操作数置位为“1”。
 * 它将当前 RLO 与边沿存储位中保存的上次 RLO 状态进行比较。
 * 如果检测到上升沿，操作数在一个程序周期内置位为“1”；否则，操作数保持为“0”。
 * 每次执行时，边沿存储位都会更新为当前 RLO 状态。
 *
 * @param in 当前逻辑运算结果（RLO，true 表示“1”，false 表示“0”）
 * @param operand 指向要置位的操作数的指针（<操作数 1>）
 * @param bit 指向边沿存储位的指针（<操作数 2>），保存上一次 RLO 状态
 */
Bool PCoil(Bool in, Bool* operand, Bool* bit) {
    if (operand == NULL || bit == NULL) return false;
  // 检查上升沿：上一次 RLO 为 0，当前 RLO 为 1
	if(!in){
		*bit = false;
		*operand  = false;
		return false;
	}
	
  if(!(*bit) && in) {
    *operand = true; // 检测到上升沿，置位操作数为 1
  }else{
		*operand = false; //其他情况为false
	}

  // 更新边沿存储位为当前 RLO 状态
  *bit = in;
  return true;
}

/**
 * @brief 在信号下降沿置位操作数
 *
 * 该函数检测逻辑运算结果（RLO）的下降沿（从“1”变为“0”），并在检测到下降沿时将指定操作数置位为“1”。
 * 它将当前 RLO 与边沿存储位中保存的上次 RLO 状态进行比较。
 * 如果检测到下降沿，操作数在一个程序周期内置位为“1”；否则，操作数保持为“0”。
 * 每次执行时，边沿存储位都会更新为当前 RLO 状态。
 *
 * @param in 当前逻辑运算结果（RLO，true 表示“1”，false 表示“0”）
 * @param operand 指向要置位的操作数的指针（<操作数 1>）
 * @param bit 指向边沿存储位的指针（<操作数 2>），保存上一次 RLO 状态
 */
Bool NCoil(Bool in, Bool* operand, Bool* bit) {
 if (operand == NULL || bit == NULL) return false;
  // 检查下降沿：上一次 RLO 为 1，当前 RLO 为 0
	if(in){
		*bit = true;
		*operand = false;
		return in;
	}
  if(*bit && !in) {
    *operand = true; // 检测到下降沿，置位操作数为 1
  }else{
		*operand = false;
	}

  // 更新边沿存储位为当前 RLO 状态
  *bit = in;
  return in;
}
Bool Not(Bool in) {
  return !in;
}


/**
 * @brief 使用“扫描 RLO 的信号上升沿”指令，可查询逻辑运算结果 (RLO) 的信号状态从“0”到“1”的更改。该指令将比较 RLO
 * 的当前信号状态与保存在边沿存储位（<操作数>）中上一次查询的信号状态。如果该指令检测到 RLO
 * 从“0”变为“1”，则说明出现了一个信号上升沿。每次执行指令时，都会查询信号上升沿。检测到信号上升沿时，该指令输出 Q
 * 将立即返回程序代码长度的信号状态“1”。在其它任何情况下，该输出返回的信号状态均为“0”。
 *
 * @param in       当前 RLO 值
 * @param operand  输出参数，检测结果
 * @param bit      输入参数，保存上一次的 RLO 值
 * @return Bool    返回是否检测到上升沿（1 表示检测到）
 */

// TODO 该函数待测——名字需要对应
// P_TRIG：上升沿检测器
Bool P_TRIG(Bool in, Bool* lastState) {
    if (lastState == NULL) {
        return false;  // 空指针保护
    }

    // 上升沿检测：上一次为 0，现在为 1
    Bool rising = (!(*lastState) && in) ? true : false;

    // 更新状态为当前值
    *lastState = in;

    // 返回检测结果
    return rising;
}
/**
 * @brief 使用“扫描 RLO 的信号下降沿”指令，可查询逻辑运算结果 (RLO) 的信号状态从“1”到“0”的更改。该指令将比较 RLO
的当前信号状态与保存在边沿存储位（<操作数>）中上一次查询的信号状态。如果该指令检测到 RLO
从“1”变为“0”，则说明出现了一个信号下降沿
每次执行指令时，都会查询信号下降沿。检测到信号下降沿时，该指令输出 Q
将立即返回程序代码长度的信号状态“1”。在其它任何情况下，该指令输出的信号状态均为“0”。

 *
 * @param in       当前 RLO 值
 * @param operand  输出参数，检测结果
 * @param bit      输入参数，保存上一次的 RLO 值
 * @return Bool    返回是否检测到下降沿（1 表示检测到）
 */
// TODO 该函数待测——名字需要对应
// N_TRIG：下降沿检测器（falling edge detection）
Bool N_TRIG(Bool in, Bool* lastState) {
    if (lastState == NULL) {
        return false;  // 空指针保护
    }

    // 检测下降沿：上次为 1，现在为 0
    Bool falling = (*lastState && !in) ? true : false;

    // 更新当前输入状态
    *lastState = in;

    // 返回检测结果
    return falling;
}

